#!/usr/bin/env node
/**
 * 构建分析脚本
 * 分析构建产物的大小和分布
 */

import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

const distPath = path.join(__dirname, '../dist')

/**
 * 获取文件大小（字节）
 */
function getFileSize(filePath) {
  try {
    const stats = fs.statSync(filePath)
    return stats.size
  } catch {
    return 0
  }
}

/**
 * 格式化文件大小
 */
function formatSize(bytes) {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return (bytes / Math.pow(k, i)).toFixed(2) + ' ' + sizes[i]
}

/**
 * 递归获取目录下所有文件
 */
function getAllFiles(dir, fileList = []) {
  const files = fs.readdirSync(dir)

  files.forEach((file) => {
    const filePath = path.join(dir, file)
    if (fs.statSync(filePath).isDirectory()) {
      getAllFiles(filePath, fileList)
    } else {
      fileList.push(filePath)
    }
  })

  return fileList
}

/**
 * 分析构建产物
 */
function analyzeBuild() {
  if (!fs.existsSync(distPath)) {
    console.error('❌ dist 目录不存在，请先运行 npm run build')
    process.exit(1)
  }

  console.log('📊 开始分析构建产物...\n')

  const allFiles = getAllFiles(distPath)
  const filesByType = {
    js: [],
    css: [],
    images: [],
    fonts: [],
    other: [],
  }

  let totalSize = 0
  let totalGzipSize = 0

  // 分类文件
  allFiles.forEach((file) => {
    const ext = path.extname(file).toLowerCase()
    const size = getFileSize(file)
    const relativePath = path.relative(distPath, file)
    totalSize += size

    const fileInfo = { path: relativePath, size }

    // 检查是否有对应的 .gz 文件
    const gzFile = file + '.gz'
    if (fs.existsSync(gzFile)) {
      fileInfo.gzipSize = getFileSize(gzFile)
      totalGzipSize += fileInfo.gzipSize
    }

    if (ext === '.js') {
      filesByType.js.push(fileInfo)
    } else if (ext === '.css') {
      filesByType.css.push(fileInfo)
    } else if (['.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico', '.webp'].includes(ext)) {
      filesByType.images.push(fileInfo)
    } else if (['.woff', '.woff2', '.ttf', '.eot', '.otf'].includes(ext)) {
      filesByType.fonts.push(fileInfo)
    } else if (ext !== '.gz') {
      filesByType.other.push(fileInfo)
    }
  })

  // 排序（按大小降序）
  Object.keys(filesByType).forEach((type) => {
    filesByType[type].sort((a, b) => b.size - a.size)
  })

  // 打印分析结果
  console.log('=' .repeat(80))
  console.log('📦 构建产物总览')
  console.log('=' .repeat(80))
  console.log(`总文件大小: ${formatSize(totalSize)}`)
  if (totalGzipSize > 0) {
    console.log(`Gzip 压缩后: ${formatSize(totalGzipSize)} (压缩率: ${((1 - totalGzipSize / totalSize) * 100).toFixed(1)}%)`)
  }
  console.log(`文件总数: ${allFiles.filter((f) => !f.endsWith('.gz')).length}`)
  console.log()

  // JavaScript 文件
  if (filesByType.js.length > 0) {
    console.log('=' .repeat(80))
    console.log('📄 JavaScript 文件')
    console.log('=' .repeat(80))
    const jsTotal = filesByType.js.reduce((sum, f) => sum + f.size, 0)
    const jsGzipTotal = filesByType.js.reduce((sum, f) => sum + (f.gzipSize || 0), 0)
    console.log(`总大小: ${formatSize(jsTotal)}`)
    if (jsGzipTotal > 0) {
      console.log(`Gzip 后: ${formatSize(jsGzipTotal)}`)
    }
    console.log()

    filesByType.js.forEach((file) => {
      const gzipInfo = file.gzipSize ? ` → ${formatSize(file.gzipSize)} (gzipped)` : ''
      const warning = file.size > 500 * 1024 ? ' ⚠️  超过 500KB' : ''
      console.log(`  ${formatSize(file.size).padStart(10)} ${file.path}${gzipInfo}${warning}`)
    })
    console.log()
  }

  // CSS 文件
  if (filesByType.css.length > 0) {
    console.log('=' .repeat(80))
    console.log('🎨 CSS 文件')
    console.log('=' .repeat(80))
    const cssTotal = filesByType.css.reduce((sum, f) => sum + f.size, 0)
    const cssGzipTotal = filesByType.css.reduce((sum, f) => sum + (f.gzipSize || 0), 0)
    console.log(`总大小: ${formatSize(cssTotal)}`)
    if (cssGzipTotal > 0) {
      console.log(`Gzip 后: ${formatSize(cssGzipTotal)}`)
    }
    console.log()

    filesByType.css.forEach((file) => {
      const gzipInfo = file.gzipSize ? ` → ${formatSize(file.gzipSize)} (gzipped)` : ''
      console.log(`  ${formatSize(file.size).padStart(10)} ${file.path}${gzipInfo}`)
    })
    console.log()
  }

  // 图片文件
  if (filesByType.images.length > 0) {
    console.log('=' .repeat(80))
    console.log('🖼️  图片文件')
    console.log('=' .repeat(80))
    const imgTotal = filesByType.images.reduce((sum, f) => sum + f.size, 0)
    console.log(`总大小: ${formatSize(imgTotal)}`)
    console.log(`文件数: ${filesByType.images.length}`)
    console.log()

    filesByType.images.slice(0, 5).forEach((file) => {
      console.log(`  ${formatSize(file.size).padStart(10)} ${file.path}`)
    })
    if (filesByType.images.length > 5) {
      console.log(`  ... 还有 ${filesByType.images.length - 5} 个图片文件`)
    }
    console.log()
  }

  // 建议
  console.log('=' .repeat(80))
  console.log('💡 优化建议')
  console.log('=' .repeat(80))

  const largeJsFiles = filesByType.js.filter((f) => f.size > 500 * 1024)
  if (largeJsFiles.length > 0) {
    console.log('⚠️  发现大型 JS 文件:')
    largeJsFiles.forEach((file) => {
      console.log(`   - ${file.path} (${formatSize(file.size)})`)
    })
    console.log('   建议: 使用代码分割或按需导入优化这些文件')
    console.log()
  }

  const largeImages = filesByType.images.filter((f) => f.size > 100 * 1024)
  if (largeImages.length > 0) {
    console.log('⚠️  发现大型图片文件:')
    largeImages.forEach((file) => {
      console.log(`   - ${file.path} (${formatSize(file.size)})`)
    })
    console.log('   建议: 压缩图片或使用 WebP 格式')
    console.log()
  }

  if (totalGzipSize === 0) {
    console.log('⚠️  未检测到 Gzip 压缩文件')
    console.log('   建议: 确保 vite-plugin-compression 插件已正确配置')
    console.log()
  }

  const entryFile = filesByType.js.find((f) => f.path.includes('index'))
  if (entryFile && entryFile.gzipSize && entryFile.gzipSize > 200 * 1024) {
    console.log('⚠️  入口文件过大')
    console.log(`   入口文件: ${formatSize(entryFile.gzipSize)} (gzipped)`)
    console.log('   建议: 应小于 200KB，考虑进一步代码分割')
    console.log()
  }

  console.log('✅ 分析完成！')
  console.log()
  console.log('提示: 运行 npm run analyze 查看可视化分析报告')
  console.log('=' .repeat(80))
}

analyzeBuild()
